package com.cloudbroker.bcs.platform.ltb.middle.aspect;

import com.cloudbroker.bcs.common.annotation.NoShard;
import com.cloudbroker.bcs.common.annotation.NoToken;
import com.cloudbroker.bcs.common.constants.LogFields;
import com.cloudbroker.bcs.common.util.PrintUtil;
import com.cloudbroker.bcs.common.util.VOUtil;
import com.cloudbroker.bcs.platform.ltb.bizapi.constants.HSBCPSErrorCodes;
import com.cloudbroker.bcs.platform.ltb.bizapi.service.base.vo.BrokerPageVO;
import com.cloudbroker.bcs.platform.ltb.bizapi.service.base.vo.BrokerVO;
import com.cloudbroker.bcs.platform.ltb.bizapi.service.base.vo.HSLTBBaseVO;
import com.cloudbroker.bcs.platform.ltb.middle.mybatis.ShardContext;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * Created by zhaosh19213 on 2016/8/18.
 */
public class MybatisAspect {
    private static final String CLASS_NAME = MybatisAspect.class.getName();

    private static final Logger LOGGER = LoggerFactory.getLogger(CLASS_NAME);

    public MybatisAspect() {
        PrintUtil.printComponentLoaded(LOGGER, CLASS_NAME);
    }

    public Object bindCompanyData(ProceedingJoinPoint pjp) throws Throwable {
        // 在Spring的环境里，signature就是MethodSignature
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        // 获取Method
        Method method = methodSignature.getMethod();

        //先分库分片信息（company_id）初始化
        ShardContext shardContext = ShardContext.getShardContext();
        if (shardContext!=null) {
            ShardContext.removeShardContext();
        }

        // 方法上没有申明@NoCompany且类上也没有申明@NoCompany，则在localThread加入券商ID
        if ((!method.isAnnotationPresent(NoToken.class)
                && !method.getDeclaringClass().isAnnotationPresent(NoToken.class))&&
                (!method.isAnnotationPresent(NoShard.class)
                        && !method.getDeclaringClass().isAnnotationPresent(NoShard.class))) {
            for (Object arg : pjp.getArgs()) {
                if (arg instanceof BrokerVO ||arg instanceof BrokerPageVO) {
                    Map<String, Object> result = bindCompanyId((HSLTBBaseVO) arg);
                    if (null != result) {
                        return result;
                    }
                } else {
                    // impossible
                    throw new RuntimeException("invalid access");
                }
            }

            return pjp.proceed();
        } else {
            // 执行业务
            return pjp.proceed();
        }
    }

    private Map<String, Object> bindCompanyId(HSLTBBaseVO vo) {
        String company_id = vo.getCompany_id();
        if (null == company_id) {
            return VOUtil.genErrorResult(HSBCPSErrorCodes.ClientErr.SENDERCOMP_ID_OR_COMPANY_ID_NOTEMPTY,
                    "company_id", company_id);
        }
        //
        ShardContext shardContext = ShardContext.getShardContext();
        shardContext.setCompany_id(company_id);
        MDC.put(LogFields.COMPANY_ID, company_id);
        return null;
    }
}
